package cmodel

import (
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"mcp-demo/internal/utils/timeutil"
	"os"
	"path/filepath"
	"time"
)

type Zap struct {
	Level         string   `mapstructure:"level" json:"level" yaml:"level"`                            // 级别
	Prefix        string   `mapstructure:"prefix" json:"prefix" yaml:"prefix"`                         // 日志前缀
	Format        string   `mapstructure:"format" json:"format" yaml:"format"`                         // 输出
	Director      string   `mapstructure:"director" json:"director"  yaml:"director"`                  // 日志文件夹
	EncodeLevel   string   `mapstructure:"encode-level" json:"encode-level" yaml:"encode-level"`       // 编码级
	StacktraceKey string   `mapstructure:"stacktrace-key" json:"stacktrace-key" yaml:"stacktrace-key"` // 栈名
	ShowLine      bool     `mapstructure:"show-line" json:"show-line" yaml:"show-line"`                // 显示行
	LogInConsole  bool     `mapstructure:"log-in-console" json:"log-in-console" yaml:"log-in-console"` // 输出控制台
	RetentionDay  int      `mapstructure:"retention-day" json:"retention-day" yaml:"retention-day"`    // 日志保留天数
	MaxSize       int      `mapstructure:"max-size" json:"max-size" yaml:"max-size"`                   // 日志轮转 单个文件最大大小
	MaxBackups    int      `mapstructure:"max-backups" json:"max-backups" yaml:"max-backups"`          // 日志最大备份数 日志超限制会生成新文件, 限制文件的数量
	Filter        []string `mapstructure:"filter" json:"filter" yaml:"filter"`                         // 不打印日志的接口
}

// Levels 根据字符串转化为 zapcore.Levels
func (c *Zap) Levels() []zapcore.Level {
	levels := make([]zapcore.Level, 0, 7)
	level, err := zapcore.ParseLevel(c.Level)
	if err != nil {
		level = zapcore.DebugLevel
	}
	for ; level <= zapcore.FatalLevel; level++ {
		levels = append(levels, level)
	}
	return levels
}

func (c *Zap) Encoder() zapcore.Encoder {
	config := zapcore.EncoderConfig{
		TimeKey:       "time",
		NameKey:       "name",
		LevelKey:      "level",
		CallerKey:     "caller",
		MessageKey:    "message",
		StacktraceKey: c.StacktraceKey,
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeTime: func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendString(c.Prefix + t.Format("2006-01-02 15:04:05.000"))
		},
		EncodeLevel:    c.LevelEncoder(),
		EncodeCaller:   zapcore.FullCallerEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
	}
	if c.Format == "json" {
		return zapcore.NewJSONEncoder(config)
	}
	return zapcore.NewConsoleEncoder(config)

}

// LevelEncoder 根据 EncodeLevel 返回 zapcore.LevelEncoder
func (c *Zap) LevelEncoder() zapcore.LevelEncoder {
	switch {
	case c.EncodeLevel == "LowercaseLevelEncoder": // 小写编码器(默认)
		return zapcore.LowercaseLevelEncoder
	case c.EncodeLevel == "LowercaseColorLevelEncoder": // 小写编码器带颜色
		return zapcore.LowercaseColorLevelEncoder
	case c.EncodeLevel == "CapitalLevelEncoder": // 大写编码器
		return zapcore.CapitalLevelEncoder
	case c.EncodeLevel == "CapitalColorLevelEncoder": // 大写编码器带颜色
		return zapcore.CapitalColorLevelEncoder
	default:
		return zapcore.LowercaseLevelEncoder
	}
}

// GetLogFileWriter 文件Writer
func (c *Zap) GetLogFileWriter() zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   filepath.Join(c.Director, timeutil.TimeToStrWithFormat(time.Now(), timeutil.Format4), c.Level+".log"),
		MaxSize:    c.MaxSize,
		MaxBackups: c.MaxBackups,
		MaxAge:     c.RetentionDay,
		LocalTime:  true, // 使用本地时间
		Compress:   true, // 是否压缩 disabled by default
	}
	// 如果需要在控制台输出，则使用 MultiWriteSyncer
	if c.LogInConsole {
		return zapcore.NewMultiWriteSyncer(
			zapcore.AddSync(os.Stdout),        // 控制台输出
			zapcore.AddSync(lumberJackLogger), // 文件输出
		)
	}
	return zapcore.AddSync(lumberJackLogger)
}
